//
//  ViewController.swift
//  rxExample
//
//  Created by samlau on 10/21/2021.
//  Copyright (c) 2021 samlau. All rights reserved.
//
import RxCocoa
import RxSwift
import UIKit
import Foundation
import SnapKit
import rxExample

public enum Result<Success, Failure> where Failure: Error {
    case success(Success)
    case failure(Failure)
}

enum DataError:Error {
    case cantParseJSON
}

class ViewController3: UIViewController {
    let disposeBag = DisposeBag()
    let subjectA = PublishSubject<String>()
    let subjectB = PublishSubject<String>()
    
    override func viewDidLoad() {
        self.view.backgroundColor = UIColor.white
        
        subjectA.withLatestFrom(subjectB){(first, second) in
            return first + second
        }
        .subscribe {
            print("Subcribe:\($0)")
        } onError: {
            print("Error:\($0)")
        } onCompleted: {
            print("Completed")
        }.disposed(by: disposeBag)
        
        subjectA.onNext("1")
        subjectB.onNext("A")
        
        subjectA.onNext("2")
        subjectB.onNext("B")
        
        subjectB.onNext("C")
        subjectB.onNext("D")
        
        subjectA.onNext("3")
        subjectA.onNext("4")
        subjectA.onNext("5")
    }
}

class ViewController2: UIViewController {
    var disposeBag = DisposeBag()
    let recoverySequence = PublishSubject<String>()
    
    override func viewDidLoad() {
        self.view.backgroundColor = UIColor.white
        // 网络请求的数据
        let rzData: Observable<String> = Observable.create { obsever -> Disposable in
            obsever.onError(DataError.cantParseJSON)
            return Disposables.create()
        }
        // 本地缓存的数据
        let rxLocalData: Observable<String> = Observable.create { obsever -> Disposable in
            obsever.onNext("Local Data")
            obsever.onCompleted()
            return Disposables.create()
        }
        
        
        rzData.catchError({ _ in
            rxLocalData
        }).subscribe { str in
            print(str)
        } onError: { err in
            print(err)
        } onCompleted: {
            print("时序完成")
        }.disposed(by: disposeBag)
        
        subViews()
    }
    
    func subViews() {
        let nameButton = UIButton()
        nameButton.setTitle("Name", for: .normal)
        nameButton.backgroundColor = UIColor.orange
        self.view.addSubview(nameButton)
        
        nameButton.snp.makeConstraints { make in
            make.center.equalTo(self.view)
            make.size.equalTo(CGSize(width: 100, height: 50))
        }
        
        nameButton.rx.tap
            .observeOn(MainScheduler.instance)
            .subscribe {
            } onError: { error in
            } onCompleted: {
            }.disposed(by: disposeBag)
    }
}

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    let myTabeView:UITableView! = UITableView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height), style: .grouped)
    
    var info = [
        [
            "title":"观察者","data": [
                ["name":"AnyObserver","cls":"AnyObserverExample"]
            ],
        ],
        [
            "title":"操作符","data": [
                ["name":"map","cls":"OperatorMapExample"]
            ],
        ],
        [
            "title":"其他","data": [
                ["name":"共享附加作用","cls":"ShareController"]
            ],
        ],
        [
            "title":"示例","data": [
                ["name":"用户名、密码校验-MVVM","cls":"SimpleValidationViewController"],
                ["name":"Github登录-MVVM","cls":"GithubSignUpViewController"],
            ],
        ]
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        initViews()
        doRequest()
    }
    
    func initViews() {
        // 注册CELL
        //myTabeView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        // 代理
        myTabeView.delegate = self
        myTabeView.dataSource = self
        // 分割线样式
        myTabeView.separatorStyle = .singleLine
        // 分割线间距
        myTabeView.separatorInset = UIEdgeInsetsMake(0, 20, 0, 20)
        self.view.addSubview(myTabeView)
    }
    
    // MARK: - UITableViewDelegate
    func numberOfSections(in tableView: UITableView) -> Int {
        return info.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let dt: Array<[String:String]> = info[section]["data"] as! Array<[String:String]>
        return dt.count
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        let dt: Array<[String:String]> = info[indexPath.section]["data"] as! Array<[String:String]>
        let clsName: String = dt[indexPath.row]["cls"]!
        
        if let cls = NSClassFromString(clsName) as? UIViewController.Type {
            let vc = cls.init()
            vc.title = dt[indexPath.row]["name"]!
            self.navigationController?.pushViewController(vc, animated: true)
        }
    }
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let dt: String = info[section]["title"] as! String
        return dt
    }
    
    // MARK: - UITableViewDataSource
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let dt: Array<[String:String]> = info[indexPath.section]["data"] as! Array<[String:String]>
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "Cell")
        
        if #available(iOS 14.0, *) {
            var content = cell.defaultContentConfiguration()
            content.text = dt[indexPath.row]["name"]
            content.secondaryText = dt[indexPath.row]["cls"]
            cell.contentConfiguration = content
        } else {
            cell.textLabel?.text = dt[indexPath.row]["name"]
            cell.detailTextLabel?.text = dt[indexPath.row]["cls"]
        }
        
        return cell
    }
    
    func getAppName() -> String {
        guard let bundle = Bundle.main.infoDictionary, let appName = bundle["CFBundleName"] as? String else {
            return ""
        }
        return appName
    }
 
    
    
    func doRequest() {
        
        typealias JSON = Any
        
        let json: Observable<Data> = Observable.create { (observer) -> Disposable in
            
            let url: URL = URL(string: "http://192.168.9.16:8080/mock/myHouseLis.json")!
            let request: URLRequest = URLRequest(url: url)
            let task = URLSession.shared.dataTask(with: request) { data, _, error in
                
                guard error == nil else {
                    observer.onError(error!)
                    return
                }
                guard let data = data, let jsonObj = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) else {
                    observer.onError(DataError.cantParseJSON)
                    return
                }
                
                observer.onNext(data)
                observer.onCompleted()
            }
            
            task.resume()
            
            return Disposables.create {
                task.cancel()
            }
        }
        
        json.subscribe { json in
            let myHouseLis = try? JSONDecoder().decode(MyHouseLis.self, from: json as Data)
            var name = myHouseLis?.data?.age?.name ?? ""
            print("成功：\(json)")
        } onError: { (error) in
            print("失败：\(error)")
        } onCompleted: {
            print("取得 json 任务成功完成")
        }
    }
}

// MARK: - MyHouseLis
struct MyHouseLis: Codable {
    var code, message: String?
    var data: DataClass?
}

// MARK: - DataClass
struct DataClass: Codable {
    var houseList: [HouseList]?
    var communityID: Int?
    var age: Age?

    enum CodingKeys: String, CodingKey {
        case houseList
        case communityID
        case age
    }
}

// MARK: - Age
struct Age: Codable {
    var name: String?
}

// MARK: - HouseList
struct HouseList: Codable {
    var relID, userID, houseID, applyTime: Int?
    var applyDesc: String?
    var status, defaultFlag, communityID: Int?
    var communityName: String?
    var buildID: Int?
    var buildName: String?
    var unitID: Int?
    var unitName: String?
    var userType: Int?
    var userTypeDesc: String?
    var type, custID, custType, inTime: Int?
    var outTime, authFlag: Int?
    var authFlagDesc, roomNo, houseName, custName: String?
    var custTel, tel, name, fullHouseName: String?
    var nickName: String?
    var userCount, auditStatus, adminUserID: Int?

    enum CodingKeys: String, CodingKey {
        case relID
        case userID
        case houseID
        case applyTime, applyDesc, status, defaultFlag
        case communityID
        case communityName
        case buildID
        case buildName
        case unitID
        case unitName, userType, userTypeDesc, type
        case custID
        case custType, inTime, outTime, authFlag, authFlagDesc, roomNo, houseName, custName, custTel, tel, name, fullHouseName, nickName, userCount, auditStatus
        case adminUserID
    }
}
